home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / gcc_260.zip / gcc_260 / cp / g++.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  13KB  |  536 lines

  1. /* G++ preliminary semantic processing for the compiler driver.
  2.    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
  3.    Contributed by Brendan Kehoe (brendan@cygnus.com).
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* This program is a wrapper to the main `gcc' driver.  For GNU C++,
  22.    we need to do two special things: a) append `-lg++' in situations
  23.    where it's appropriate, to link in libg++, and b) add `-xc++'..`-xnone'
  24.    around file arguments named `foo.c' or `foo.i'.  So, we do all of
  25.    this semantic processing then just exec gcc with the new argument
  26.    list.
  27.  
  28.    We used to do all of this in a small shell script, but many users
  29.    found the performance of this as a shell script to be unacceptable.
  30.    In situations where your PATH has a lot of NFS-mounted directories,
  31.    using a script that runs sed and other things would be a nasty
  32.    performance hit.  With this program, we never search the PATH at all.  */
  33.  
  34. #include "config.h"
  35. #ifdef __STDC__
  36. #include <stdarg.h>
  37. #else
  38. #include <varargs.h>
  39. #endif
  40. #include <stdio.h>
  41. #include <sys/types.h>
  42. #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
  43.  
  44. /* Defined to the name of the compiler; if using a cross compiler, the
  45.    Makefile should compile this file with the proper name
  46.    (e.g., "i386-aout-gcc").  */
  47. #ifndef GCC_NAME
  48. #define GCC_NAME "gcc"
  49. #endif
  50.  
  51. /* This bit is set if we saw a `-xfoo' language specification.  */
  52. #define LANGSPEC    (1<<1)
  53. /* This bit is set if they did `-lm' or `-lmath'.  */
  54. #define MATHLIB        (1<<2)
  55.  
  56. /* On MSDOS, write temp files in current dir
  57.    because there's no place else we can expect to use.  */
  58. #ifdef __MSDOS__
  59. #ifndef P_tmpdir
  60. #define P_tmpdir "."
  61. #endif
  62. #ifndef R_OK
  63. #define R_OK 4
  64. #define W_OK 2
  65. #define X_OK 1
  66. #endif
  67. #endif
  68.  
  69. #ifndef VPROTO
  70. #ifdef __STDC__
  71. #define PVPROTO(ARGS)        ARGS
  72. #define VPROTO(ARGS)        ARGS
  73. #define VA_START(va_list,var)    va_start(va_list,var)
  74. #else
  75. #define PVPROTO(ARGS)        ()
  76. #define VPROTO(ARGS)        (va_alist) va_dcl
  77. #define VA_START(va_list,var)    va_start(va_list)
  78. #endif
  79. #endif
  80.  
  81. extern int errno, sys_nerr;
  82. #if defined(bsd4_4) || defined(__NetBSD__)
  83. extern const char *const sys_errlist[];
  84. #else
  85. extern char *sys_errlist[];
  86. #endif
  87.  
  88. /* Name with which this program was invoked.  */
  89. static char *programname;
  90.  
  91. #ifdef HAVE_VPRINTF
  92. /* Output an error message and exit */
  93.  
  94. static void
  95. fatal VPROTO((char *format, ...))
  96. {
  97. #ifndef __STDC__
  98.   char *format;
  99. #endif
  100.   va_list ap;
  101.  
  102.   VA_START (ap, format);
  103.  
  104. #ifndef __STDC__
  105.   format = va_arg (ap, char*);
  106. #endif
  107.  
  108.   fprintf (stderr, "%s: ", programname);
  109.   vfprintf (stderr, format, ap);
  110.   va_end (ap);
  111.   fprintf (stderr, "\n");
  112. #if 0
  113.   /* XXX Not needed for g++ driver.  */
  114.   delete_temp_files ();
  115. #endif
  116.   exit (1);
  117. }
  118.  
  119. static void
  120. error VPROTO((char *format, ...))
  121. {
  122. #ifndef __STDC__
  123.   char *format;
  124. #endif
  125.   va_list ap;
  126.  
  127.   VA_START (ap, format);
  128.  
  129. #ifndef __STDC__
  130.   format = va_arg (ap, char*);
  131. #endif
  132.  
  133.   fprintf (stderr, "%s: ", programname);
  134.   vfprintf (stderr, format, ap);
  135.   va_end (ap);
  136.  
  137.   fprintf (stderr, "\n");
  138. }
  139.  
  140. #else /* not HAVE_VPRINTF */
  141.  
  142. static void
  143. error (msg, arg1, arg2)
  144.      char *msg, *arg1, *arg2;
  145. {
  146.   fprintf (stderr, "%s: ", programname);
  147.   fprintf (stderr, msg, arg1, arg2);
  148.   fprintf (stderr, "\n");
  149. }
  150.  
  151. static void
  152. fatal (msg, arg1, arg2)
  153.      char *msg, *arg1, *arg2;
  154. {
  155.   error (msg, arg1, arg2);
  156. #if 0
  157.   /* XXX Not needed for g++ driver.  */
  158.   delete_temp_files ();
  159. #endif
  160.   exit (1);
  161. }
  162.  
  163. #endif /* not HAVE_VPRINTF */
  164.  
  165. /* More 'friendly' abort that prints the line and file.
  166.    config.h can #define abort fancy_abort if you like that sort of thing.  */
  167.  
  168. void
  169. fancy_abort ()
  170. {
  171.   fatal ("Internal g++ abort.");
  172. }
  173.  
  174. char *
  175. xmalloc (size)
  176.      unsigned size;
  177. {
  178.   register char *value = (char *) malloc (size);
  179.   if (value == 0)
  180.     fatal ("virtual memory exhausted");
  181.   return value;
  182. }
  183.  
  184. /* Return a newly-allocated string whose contents concatenate those
  185.    of s1, s2, s3.  */
  186. static char *
  187. concat (s1, s2, s3)
  188.      char *s1, *s2, *s3;
  189. {
  190.   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
  191.   char *result = xmalloc (len1 + len2 + len3 + 1);
  192.  
  193.   strcpy (result, s1);
  194.   strcpy (result + len1, s2);
  195.   strcpy (result + len1 + len2, s3);
  196.   *(result + len1 + len2 + len3) = 0;
  197.  
  198.   return result;
  199. }
  200.  
  201. static void
  202. pfatal_with_name (name)
  203.      char *name;
  204. {
  205.   char *s;
  206.  
  207.   if (errno < sys_nerr)
  208.     s = concat ("%s: ", sys_errlist[errno], "");
  209.   else
  210.     s = "cannot open %s";
  211.   fatal (s, name);
  212. }
  213.  
  214. #ifdef __MSDOS__
  215. /* This is the common prefix we use to make temp file names.  */
  216. char *temp_filename;
  217.  
  218. /* Length of the prefix.  */
  219. int temp_filename_length;
  220.  
  221. /* Compute a string to use as the base of all temporary file names.  */
  222. static char *
  223. choose_temp_base_try (try, base)
  224. char *try;
  225. char *base;
  226. {
  227.   char *rv;
  228.   if (base)
  229.     rv = base;
  230.   else if (try == (char *)0)
  231.     rv = 0;
  232.   else if (access (try, R_OK | W_OK) != 0)
  233.     rv = 0;
  234.   else
  235.     rv = try;
  236.   return rv;
  237. }
  238.  
  239. static void
  240. choose_temp_base ()
  241. {
  242.   char *base = 0;
  243.   int len;
  244.  
  245.   base = choose_temp_base_try (getenv ("TMPDIR"), base);
  246.   base = choose_temp_base_try (getenv ("TMP"), base);
  247.   base = choose_temp_base_try (getenv ("TEMP"), base);
  248.  
  249. #ifdef P_tmpdir
  250.   base = choose_temp_base_try (P_tmpdir, base);
  251. #endif
  252.  
  253.   base = choose_temp_base_try ("/usr/tmp", base);
  254.   base = choose_temp_base_try ("/tmp", base);
  255.  
  256.   /* If all else fails, use the current directory! */  
  257.   if (base == (char *)0)
  258.     base = "./";
  259.  
  260.   len = strlen (base);
  261.   temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
  262.   strcpy (temp_filename, base);
  263.   if (len > 0 && temp_filename[len-1] != '/')
  264.     temp_filename[len++] = '/';
  265.   strcpy (temp_filename + len, "ccXXXXXX");
  266.  
  267.   mktemp (temp_filename);
  268.   temp_filename_length = strlen (temp_filename);
  269.   if (temp_filename_length == 0)
  270.     abort ();
  271. }
  272.  
  273. static void
  274. perror_exec (name)
  275.      char *name;
  276. {
  277.   char *s;
  278.  
  279.   if (errno < sys_nerr)
  280.     s = concat ("installation problem, cannot exec %s: ",
  281.         sys_errlist[errno], "");
  282.   else
  283.     s = "installation problem, cannot exec %s";
  284.   error (s, name);
  285. }
  286.  
  287. /* This is almost exactly what's in gcc.c:pexecute for MSDOS.  */
  288. void
  289. run_dos (program, argv)
  290.      char *program;
  291.      char *argv[];
  292. {
  293.   char *scmd, *rf;
  294.   FILE *argfile;
  295.   int i;
  296.  
  297.   choose_temp_base (); /* not in gcc.c */
  298.  
  299.   scmd = (char *) malloc (strlen (program) + strlen (temp_filename) + 10);
  300.   rf = scmd + strlen (program) + 6;
  301.   sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
  302.  
  303.   argfile = fopen (rf, "w");
  304.   if (argfile == 0)
  305.     pfatal_with_name (rf);
  306.  
  307.   for (i=1; argv[i]; i++)
  308.     {
  309.       char *cp;
  310.       for (cp = argv[i]; *cp; cp++)
  311.     {
  312.       if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
  313.         fputc ('\\', argfile);
  314.       fputc (*cp, argfile);
  315.     }
  316.       fputc ('\n', argfile);
  317.     }
  318.   fclose (argfile);
  319.  
  320.   i = system (scmd);
  321.  
  322.   remove (rf);
  323.   
  324.   if (i == -1)
  325.     perror_exec (program);
  326. }
  327. #endif /* __MSDOS__ */
  328.  
  329. int
  330. main (argc, argv)
  331.      int argc;
  332.      char **argv;
  333. {
  334.   register int i, j = 0;
  335.   register char *p;
  336.   int verbose = 0;
  337.  
  338.   /* This will be NULL if we encounter a situation where we should not
  339.      link in libg++.  */
  340.   char *library = "-lg++";
  341.  
  342.   /* Used to track options that take arguments, so we don't go wrapping
  343.      those with -xc++/-xnone.  */
  344.   char *quote = NULL;
  345.  
  346.   /* The new argument list will be contained in this.  */
  347.   char **arglist;
  348.  
  349.   /* The name of the compiler we will want to run---by default, it
  350.      will be the definition of `GCC_NAME', e.g., `gcc'.  */
  351.   char *gcc = GCC_NAME;
  352.  
  353.   /* Non-zero if we saw a `-xfoo' language specification on the
  354.      command line.  Used to avoid adding our own -xc++ if the user
  355.      already gave a language for the file.  */
  356.   int saw_speclang = 0;
  357.  
  358.   /* Non-zero if we saw `-lm' or `-lmath' on the command line.  */
  359.   int saw_math = 0;
  360.  
  361.   /* The number of arguments being added to what's in argv.  By
  362.      default it's one new argument (adding `-lg++').  We use this
  363.      to track the number of times we've inserted -xc++/-xnone as well.  */
  364.   int added = 1;
  365.  
  366.   /* An array used to flag each argument that needs a bit set for
  367.      LANGSPEC or MATHLIB.  */
  368.   int *args;
  369.  
  370.   p = argv[0] + strlen (argv[0]);
  371.   while (p != argv[0] && p[-1] != '/')
  372.     --p;
  373.   programname = p;
  374.  
  375.   if (argc == 1)
  376.     fatal ("No input files specified.\n");
  377.  
  378. #ifndef __MSDOS__
  379.   /* We do a little magic to find out where the main gcc executable
  380.      is.  If they ran us as /usr/local/bin/g++, then we will look
  381.      for /usr/local/bin/gcc; similarly, if they just ran us as `g++',
  382.      we'll just look for `gcc'.  */
  383.   if (p != argv[0])
  384.     {
  385.       *--p = '\0';
  386.       gcc = (char *) malloc ((strlen (argv[0]) + 1 + strlen (GCC_NAME) + 1)
  387.                  * sizeof (char));
  388.       sprintf (gcc, "%s/%s", argv[0], GCC_NAME);
  389.     }
  390. #endif
  391.  
  392.   args = (int *) malloc (argc * sizeof (int));
  393.   bzero (args, argc * sizeof (int));
  394.  
  395.   for (i = 1; i < argc; i++)
  396.     {
  397.       /* If the previous option took an argument, we swallow it here.  */
  398.       if (quote)
  399.     {
  400.       quote = NULL;
  401.       continue;
  402.     }
  403.  
  404.       if (argv[i][0] == '\0' || argv[i][1] == '\0')
  405.     continue;
  406.  
  407.       if (argv[i][0] == '-')
  408.     {
  409.       if (strcmp (argv[i], "-nostdlib") == 0)
  410.         {
  411.           added--;
  412.           library = NULL;
  413.         }
  414.       else if (strcmp (argv[i], "-lm") == 0
  415.            || strcmp (argv[i], "-lmath") == 0)
  416.         args[i] |= MATHLIB;
  417.       else if (strcmp (argv[i], "-v") == 0)
  418.         {
  419.           verbose = 1;
  420.           if (argc == 2)
  421.         {
  422.           /* If they only gave us `-v', don't try to link
  423.              in libg++.  */ 
  424.           added--;
  425.           library = NULL;
  426.         }
  427.         }
  428.       else if (strncmp (argv[i], "-x", 2) == 0)
  429.         saw_speclang = 1;
  430.       else if (((argv[i][2] == '\0'
  431.              && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
  432.             || strcmp (argv[i], "-Tdata") == 0))
  433.         quote = argv[i];
  434.       else if (((argv[i][2] == '\0'
  435.              && (char *) strchr ("cSEM", argv[i][1]) != NULL)
  436.             || strcmp (argv[i], "-MM") == 0))
  437.         {
  438.           /* Don't specify libraries if we won't link, since that would
  439.          cause a warning.  */
  440.           added--;
  441.           library = NULL;
  442.         }
  443.       else
  444.         /* Pass other options through.  */
  445.         continue;
  446.     }
  447.       else
  448.     {
  449.       int len; 
  450.  
  451.       if (saw_speclang)
  452.         continue;
  453.  
  454.       /* If the filename ends in .c or .i, put options around it.
  455.          But not if a specified -x option is currently active.  */
  456.       len = strlen (argv[i]);
  457.       if (len > 2
  458.           && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
  459.           && argv[i][len - 2] == '.')
  460.         {
  461.           args[i] |= LANGSPEC;
  462.           added += 2;
  463.         }
  464.     }
  465.     }
  466.  
  467.   if (quote)
  468.     fatal ("argument to `%s' missing\n", quote);
  469.  
  470.   if (added)
  471.     {
  472.       arglist = (char **) malloc ((argc + added + 1) * sizeof (char *));
  473.  
  474.       for (i = 1, j = 1; i < argc; i++, j++)
  475.     {
  476.       arglist[j] = argv[i];
  477.  
  478.       /* Make sure -lg++ is before the math library, since libg++
  479.          itself uses those math routines.  */
  480.       if (!saw_math && (args[i] & MATHLIB) && library)
  481.         {
  482.           saw_math = 1;
  483.           arglist[j] = library;
  484.           arglist[++j] = argv[i];
  485.         }
  486.  
  487.       /* Wrap foo.c and foo.i files in a language specification to
  488.          force the gcc compiler driver to run cc1plus on them.  */
  489.       if (args[i] & LANGSPEC)
  490.         {
  491.           int len = strlen (argv[i]);
  492.           if (argv[i][len - 1] == 'i')
  493.         arglist[j++] = "-xc++-cpp-output";
  494.           else
  495.         arglist[j++] = "-xc++";
  496.           arglist[j++] = argv[i];
  497.           arglist[j] = "-xnone";
  498.         }
  499.     }
  500.  
  501.       /* Add `-lg++' if we haven't already done so.  */
  502.       if (library && !saw_math)
  503.     arglist[j++] = library;
  504.  
  505.       arglist[j] = NULL;
  506.     }
  507.   else
  508.     /* No need to copy 'em all.  */
  509.     arglist = argv;
  510.  
  511.   arglist[0] = gcc;
  512.  
  513.   if (verbose)
  514.     {
  515.       if (j == 0)
  516.     j = argc;
  517.  
  518.       for (i = 0; i < j; i++)
  519.     fprintf (stderr, " %s", arglist[i]);
  520.       fprintf (stderr, "\n");
  521.     }
  522. #ifndef OS2
  523. #ifdef __MSDOS__
  524.   run_dos (gcc, arglist);
  525. #else /* !__MSDOS__ */
  526.   if (execvp (gcc, arglist) < 0)
  527.     pfatal_with_name (gcc);
  528. #endif /* __MSDOS__ */
  529. #else /* OS2 */
  530.   if (spawnvp (gcc, arglist) < 0)
  531.     pfatal_with_name (gcc);
  532. #endif
  533.  
  534.   return 0;
  535. }
  536.